#include "InputManager.hpp"
#include "InputEventListener.hpp"
#include "KeysDefinitions.hpp"

using namespace std;

InputManager* InputManager::m_pInstance = 0;

void InputManager::createInstance()
{
	if(!m_pInstance)
		m_pInstance = new InputManager();
}

void InputManager::destroyInstance()
{
	delete m_pInstance; m_pInstance = NULL;
}

InputManager* InputManager::getInstance()
{
	return m_pInstance;
}

InputManager::InputManager()
{
	resetKeysMap();
}

InputManager::~InputManager()
{
}

void InputManager::receiveKeyboardPress(unsigned char key, int x, int y)
{
	InputEvent* pEvent = new InputEvent();
	pEvent->m_iKeyCode = key;
	pEvent->m_iXCoord = x;
	pEvent->m_iYCoord = y;
	pEvent->m_eEventType = KEYBOARD_EVENT_T;

	getInstance()->m_keysMap[key] = KEY_PRESSED;

	getInstance()->propagateEvent(pEvent);
}

void InputManager::receiveKeyboardRelease(unsigned char key, int x, int y)
{
	getInstance()->m_keysMap[key] = KEY_RELEASED;
}

void InputManager::receiveKeyboardSpecialPress(int key, int x, int y)
{
	InputEvent* pEvent = new InputEvent();
	pEvent->m_iKeyCode = getInstance()->translateSpecialKey(key);
	pEvent->m_iXCoord = x;
	pEvent->m_iYCoord = y;
	pEvent->m_eEventType = KEYBOARD_EVENT_T;

	getInstance()->m_keysMap[pEvent->m_iKeyCode] = KEY_PRESSED;

	getInstance()->propagateEvent(pEvent);
}

void InputManager::receiveKeyboardSpecialRelease(int key, int x, int y)
{
	int iTranslatedKey = getInstance()->translateSpecialKey(key);
	getInstance()->m_keysMap[iTranslatedKey] = KEY_RELEASED;
}

void InputManager::receiveMouseActiveEvent()
{
}

void InputManager::receiveMousePassiveEvent()
{
}

void InputManager::registerListener(InputEventListener *pListener, EVENT_TYPE eListenedType)
{
	if(eListenedType == KEYBOARD_EVENT_T)
		m_keybrdListeners.push_back(pListener);
	else if(eListenedType == MOUSE_EVENT_T)
		m_mouseListeners.push_back(pListener);
}

void InputManager::propagateEvent(InputEvent *pEvent)
{
	vector<InputEventListener*>::iterator currListener;
	vector<InputEventListener*>::iterator endListeners;

	if(pEvent->m_eEventType == KEYBOARD_EVENT_T)
	{
		currListener = m_keybrdListeners.begin();
		endListeners = m_keybrdListeners.end();
	}
	else if(pEvent->m_eEventType == MOUSE_EVENT_T)
	{
		currListener = m_mouseListeners.begin();
		endListeners = m_mouseListeners.end();
	}

	for(currListener; currListener != endListeners; ++currListener)
	{
		(*currListener)->handleEvent(pEvent);
	}
}

KEY_STATUS InputManager::lookUpKeyStatus(int iKeyCode)
{
	return m_keysMap[iKeyCode];
}

void InputManager::resetKeysMap()
{
	m_keysMap[KEY_W]     = KEY_RELEASED;
	m_keysMap[KEY_S]     = KEY_RELEASED;
	m_keysMap[KEY_A]     = KEY_RELEASED;
	m_keysMap[KEY_D]     = KEY_RELEASED;
	m_keysMap[KEY_ESC]   = KEY_RELEASED;
	m_keysMap[KEY_CTRL]  = KEY_RELEASED;
	m_keysMap[KEY_UP]    = KEY_RELEASED;
	m_keysMap[KEY_DOWN]  = KEY_RELEASED;
	m_keysMap[KEY_LEFT]  = KEY_RELEASED;
	m_keysMap[KEY_RIGHT] = KEY_RELEASED;
	m_keysMap[KEY_SPACE] = KEY_RELEASED;
}

int InputManager::translateSpecialKey(int iKeyCode)
{
	switch(iKeyCode)
	{
	case 100:
		return KEY_LEFT;
	case 101:
		return KEY_UP;
	case 102:
		return KEY_RIGHT;
	case 103:
		return KEY_DOWN;
	}

	return 0;
}

//EOF
